package com.example.app.service.impl;

import com.example.app.constants.CommonConstants;
import com.example.app.constants.StateConstants;
import com.example.app.dao.AccountChangeDetailsRepository;
import com.example.app.dao.AppProductRecordRepository;
import com.example.app.dao.MemberDiscountRepository;
import com.example.app.dao.MemberRepository;
import com.example.app.dao.PaymentDetailsRepository;
import com.example.app.dao.RechargeRecordRepository;
import com.example.app.dao.mongdb.MongoMemberLevelRepository;
import com.example.app.dto.Result;
import com.example.app.model.AccountChangeDetails;
import com.example.app.model.AppProductRecord;
import com.example.app.model.Member;
import com.example.app.model.MemberDiscount;
import com.example.app.model.MemberLevel;
import com.example.app.model.PaymentDetails;
import com.example.app.model.RechargeRecord;
import com.example.app.service.MemberLevelService;
import com.example.app.service.MemberService;
import com.example.app.utils.BusinessUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.Map;

/**
 * Created by wangtao on 2018/6/6.
 */
@Service
public class MemberServiceImpl implements MemberService {

    private static final Logger logger = Logger.getLogger(MemberServiceImpl.class);

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private MemberDiscountRepository memberDiscountRepository;

    @Autowired
    private RechargeRecordRepository rechargeRecordRepository;

    @Autowired
    private MemberLevelService memberLevelService;

    @Autowired
    private PaymentDetailsRepository paymentDetailsRepository;

    @Autowired
    private AccountChangeDetailsRepository changeDetailsRepository;

    @Autowired
    private MongoMemberLevelRepository mongoMemberLevelRepository;

    @Autowired
    private AppProductRecordRepository appProductRecordRepository;

    @Override
    public Member findOne(Long id) {
        return memberRepository.findOne(id);
    }

    @Override
    public Member findByPhone(String phone) {
        return memberRepository.findByPhone(phone);
    }

    @Override
    @Transactional
    public Result doAppRecharge(Map map) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        result.setMsg("充值反馈成功");
        Long memberId = Long.valueOf(map.get("memberId").toString());
        BigDecimal rechargeAmount = new BigDecimal(map.get("money").toString());
        Member member = memberRepository.findOne(memberId);
        if (member == null) {
            result.setCode(CommonConstants.FAILURE);
            result.setMsg("查询会员信息异常");
            return result;
        }
        // 账户变动信息
        AccountChangeDetails changeDetails = new AccountChangeDetails();
        // 记录充值前账户信息
        beforeAccount(changeDetails, member);
        // 会员储值账户
        BigDecimal storeAccount = member.getStoreAccount();
        // 会员累计金额
        BigDecimal memberAmount = member.getMemberAmount();
        // 累计充值
        BigDecimal totalStoreAmount = member.getTotalStoreAmount();
        // 充值到储值账户
        storeAccount = storeAccount.add(rechargeAmount);
        // 累加充值金额
        totalStoreAmount = totalStoreAmount.add(rechargeAmount);
        // 是否累计会员金额
        int isGrand = 0;
        // 计算折扣
        if (member.getLevelId() != null) {
            MemberLevel level = memberLevelService.findOne(member.getLevelId());
            if (level != null) {
                // 指定充值金额
                BigDecimal storeAmount = level.getStoreAmount();
                // 本次充值金额大于指定充值金额
                if (rechargeAmount.compareTo(storeAmount) > 0) {
                    isGrand = 1;
                    memberAmount = memberAmount.add(rechargeAmount);
                    // 会员累计金额大于指定升级金额
                    level = getLevel(level, memberAmount);
                    member.setLevelId(level.getId());
                    member.setLevelName(level.getLevelName());
                    // 更新会员折扣
                    MemberDiscount memberDiscount = memberDiscountRepository.findByMemberIdAndDeleteFlag(member.getId(), 0);
                    if (memberDiscount != null) {
                        memberDiscount.setDiscount(level.getDiscount());
                    } else {
                        memberDiscount = new MemberDiscount();
                        memberDiscount.setPatientId(member.getPatientId());
                        memberDiscount.setMemberId(member.getId());
                        memberDiscount.setDiscountName("会员折扣");
                        memberDiscount.setDiscount(level.getDiscount());
                    }
                    BusinessUtil.appendRecord(memberDiscount);
                    memberDiscountRepository.save(memberDiscount);
                }
            }
        }
        // 生成充值记录
        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setPatientId(member.getPatientId());
        rechargeRecord.setMemberId(member.getId());
        rechargeRecord.setMemberName(member.getMemberName());
        rechargeRecord.setMemberNumber(member.getMemberNumber());
        rechargeRecord.setRechargeAmount(rechargeAmount);
        rechargeRecord.setIsGrand(isGrand);
        rechargeRecord.setSource(StateConstants.SOURCE_WECHAT_APP);
        BusinessUtil.appendRecord(rechargeRecord);
        rechargeRecordRepository.save(rechargeRecord);

        // 生成付款记录
        PaymentDetails paymentDetails = new PaymentDetails();
        paymentDetails.setRecordId(rechargeRecord.getId());
        paymentDetails.setWechat(rechargeAmount);
        paymentDetailsRepository.save(paymentDetails);

        // 更新会员信息
        member.setStoreAccount(storeAccount);
        member.setMemberAmount(memberAmount);
        member.setTotalStoreAmount(totalStoreAmount);
        BusinessUtil.appendRecord(member);
        memberRepository.save(member);

        // 记录账户变动后的信息
        afterAccount(changeDetails, member);
        changeDetails.setRecordId(rechargeRecord.getId());
        // 保存账户变动
        changeDetailsRepository.save(changeDetails);
        return result;
    }

    // 充值前账户信息
    public void beforeAccount(AccountChangeDetails changeDetails, Member member) {
        changeDetails.setBeforeStoreAccount(member.getStoreAccount());
        changeDetails.setBeforeGiftAccount(member.getGiftAccount());
        changeDetails.setBeforeCourseAccount(member.getCourseAccount());
        changeDetails.setBeforeMemberAmount(member.getMemberAmount());
        changeDetails.setBeforeLevelName(member.getLevelName());
    }

    // 充值后账户信息
    public void afterAccount(AccountChangeDetails changeDetails, Member member) {
        changeDetails.setAfterStoreAccount(member.getStoreAccount());
        changeDetails.setAfterGiftAccount(member.getGiftAccount());
        changeDetails.setAfterCourseAccount(member.getCourseAccount());
        changeDetails.setAfterMemberAmount(member.getMemberAmount());
        changeDetails.setAfterLevelName(member.getLevelName());
    }

    // 递归取得本次充值后对应的会员等级
    public MemberLevel getLevel(MemberLevel level, BigDecimal memberAmount) {
        if (memberAmount.compareTo(level.getUpAmount()) > 0) {
            if (level.getNextLevelId() != null) {
                level = mongoMemberLevelRepository.findOne(level.getNextLevelId());
                if (level != null) {
                    getLevel(level, memberAmount);
                }
            }
        }
        return level;
    }

    @Override
    @Transactional
    public Result doCreateHistory(AppProductRecord record) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        result.setMsg("保存成功");
        Member member = memberRepository.findOne(record.getMemberId());
        if(member != null){
            result.setCode(CommonConstants.FAILURE);
            result.setMsg("会员信息查询异常");
            return result;
        }
        record.setAccountId(member.getAccountId());
        record.setUserId(member.getUserId());
        record.setOrganId(member.getOrganId());
        record.setOrganName(member.getOrganName());
        BusinessUtil.appendRecord(record);
        appProductRecordRepository.save(record);
        return result;
    }
}
